package cn.ali.service.impl;

import cn.ali.bean.Student;
import cn.ali.mapper.StudentMapper;
import cn.ali.service.StudentService;
import org.apache.ibatis.binding.MapperProxy;
import org.apache.ibatis.session.SqlSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;

@Service
public class StudentServiceImpl implements StudentService {
    @Autowired
    private StudentMapper studentMapper;

    public StudentMapper getStudentMapper() {
        return studentMapper;
    }

    public void setStudentMapper(StudentMapper studentMapper) {
        this.studentMapper = studentMapper;
    }

    /**
     * 如果有事务,里面所有的mapper是使用同一个 sqlsession,一级缓存起作用,(二级默认不会开启)
     * 如果没有事务,每个mapper都会创建一个新的sqlsession,一级缓存没有作用,如果开启的二级缓存,查询同一个mapper,会从缓存中查询
     * @param id
     * @return
     */
//    @Transactional
    public Student queryUserById(long id) {
        long i = 1 / id;

        Student student = studentMapper.queryUserById(id);
        System.out.println("第一次查询=================" + student);

        Student student2 = studentMapper.queryUserById(id);
        System.out.println("第二次查询=================" + student2);

        SqlSession sqlSession = getSqlSessionFromMapperInstance(studentMapper);
        System.out.println("当前的线程为：" + Thread.currentThread() + ",当前的sqlsession=" + sqlSession);
        return student;
    }

    @Transactional
    public void update(Student student,boolean error) {
        studentMapper.update(student);
        if(error){
            int i=1/0;
        }
    }

    private SqlSession getSqlSessionFromMapperInstance(Object pvMapper) {
        if (!Proxy.isProxyClass(pvMapper.getClass())) return null;
        InvocationHandler lvInvHandler = Proxy.getInvocationHandler(pvMapper);
        if (!(lvInvHandler instanceof MapperProxy)) return null;
        MapperProxy lvT = (MapperProxy) lvInvHandler;
        try {
            Field lvSessField = lvT.getClass().getDeclaredField("sqlSession");
            lvSessField.setAccessible(true);
            try {
                return (SqlSession) lvSessField.get(lvT);
            } catch (IllegalAccessException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        } catch (SecurityException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        }
        return null;

    }
}
